package hw3.proxy.core;

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;

import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.impl.DefaultHttpClientConnection;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;

/**
 * This class is responsible for handling the communication with origin servers.
 * 
 * @author Adam Levi
 * @author Marina Skarbovsky
 *
 */
public class OriginSrvConnHandler
{
	/**
	 * Constructor
	 * 
	 */
	public OriginSrvConnHandler()
	{
		m_httpConnectionParams = new BasicHttpParams();
		ConfigurationProperties.initializeHTTPConnectionParams(m_httpConnectionParams);
	}
	
	/**
	 * Sends an HTTP request to an origin server and returns the response the server returned
	 * @param request - HTTP request
	 * @return a clone of the server's response to the request.
	 * @throws IOException
	 * @throws HttpException
	 */
	public HttpResponse getResponseToRequest(HttpRequest request) throws IOException, HttpException
	{
		InetAddress originSrvAddr = InetAddress.getByName(HttpMsgHandler.getHostName(request));
		Socket origSrvSocket = new Socket(originSrvAddr,ConfigurationProperties.HTTP_SERVER_PORT);
		DefaultHttpClientConnection conn = new DefaultHttpClientConnection();
		conn.bind(origSrvSocket, m_httpConnectionParams);
		conn.sendRequestHeader(request);
		conn.flush();
		HttpResponse response = conn.receiveResponseHeader();
		if (HttpMsgHandler.isResponseEntityAvailable(response))
		{
			conn.receiveResponseEntity(response);
		}
		if (HttpMsgHandler.isTokenReplacementAllowed(response))
		{
			HttpResponse clonedResponse = HttpMsgHandler.cloneResponse(response);
			return clonedResponse;		
		}
		return response;
	}
	
	/**
	 * performs verification of a cached resource with the origin server responsible for the resource.
	 * @param uri - resource's URI.
	 * @param eTag - value of the "ETag" header of the resource.
	 * @param lastModified -  value of the "Last-Modified" header of the resource.
	 * @return if the cached resource is valid, null is returned. 
	 * Otherwise, the validation fails, and the HTTP response gotten from the origin server, 
	 * which contains a fresh copy of the resource, will be returned.
	 * @throws IOException
	 * @throws HttpException
	 */
	public HttpResponse verifyCacheEntry(String uri, String eTag, String lastModified) throws IOException, HttpException
	{
		HttpRequest verificationRequest = HttpMsgHandler.createValidationRequest(uri, lastModified, eTag);
		HttpResponse response = getResponseToRequest(verificationRequest);
		if (response.getStatusLine().getStatusCode() == 304)
		{
			return null;
		}
		else
		{
			return response;
		}
	}
	
	private HttpParams m_httpConnectionParams;
}
